﻿
Date.prototype.format = function (formatter) {
    return moment.tz(this, _config_.format.default.timezone).format(formatter);
};

/*
* string extensions start
*/

String.prototype.getNumber = function () {
    if (this === "" || this === null || this === undefined) {
        return 0;
    }
    return numeral().unformat(this);
};

String.prototype.formatMonery = function (formatType) {
    if (!formatType) {
        formatType = '0,0.00';
    }
    return numeral(this).format(formatType);
};

String.prototype.formatMileage = function (formatType) {
    if (!formatType) {
        formatType = '0,0.0';
    }
    return numeral(this).format(formatType);
};

String.prototype.hashCode = function () {
    var hash = 0, i, chr;
    if (this.length === 0) return hash;
    for (i = 0; i < this.length; i++) {
        chr = this.charCodeAt(i);
        hash = (hash << 5) - hash + chr;
        hash |= 0; // Convert to 32bit integer
    }
    return hash;
};

/*
* object array extensions start
*/

/**
 * alias of Array.filter method
 * @param {any} callback
 */
Array.prototype.where = function (callback) {
    return this.filter(callback);
};

// get the key's value array of the object data array
// callback is reference of filter function
Array.prototype.select = function (key, callback) {
    let data = $.com.isFunction(callback) ? this.filter(callback) : this;
    if ($.com.isArray(data)) {
        var array = [];
        var cur;
        data.forEach(element => {
            cur = $.com.getValue(element, key);
            if ($.com.hasValue(cur)) {
                array.push(cur);
            }
        });

        return array;
    }

    return undefined;
};

/**
 * alias of Array.find method
 * @param {any} callback
 */
Array.prototype.first = function (callback) {
    return this.find(callback);
};

/**
 * alias of Array.some method
 * @param {any} callback
 */
Array.prototype.exist = function (callback) {
    return this.some(callback);
};

//get the first object from a data array, and select the key value
Array.prototype.firstValue = function (callback, field) {
    let first = $.com.isFunction(callback) ? this.find(callback) : this[0];
    if (typeof first !== 'undefined') {
        return first[field || "Name"];
    }

    return undefined;
};

// distinct function of object data array
// keys is array of distinct field
Array.prototype.distinct = function (key) {
    var data = this;
    var arr = [];
    if (data.length !== 0) {
        var keys = key;
        keys = (keys || 'Name').split(',');
        for (var i = data.length; i > 0; i--) {
            var exist = true;
            var x = data[i - 1];
            //if current is string value, then ignore the keys
            if (typeof x === 'object') {
                $.each(keys, function (j, y) {
                    exist = exist && arr.exist(function (z) {
                        return z[y] === x[y];
                    });
                });
            } else {
                exist = arr.exist(function (y) {
                    return y === x;
                });
            }

            if (!exist) {
                arr.push(x);
            }
        }
    }

    return arr;
};

// insert item into array index position
Array.prototype.insert = function (item, index) {
    index = index || 0;
    this.splice(index, 0, item);
};

Array.prototype.sum = function () {
    return this.reduce(function (partial, value) {
        return partial + value;
    })
};

// insert item into array index position
Array.prototype.remove = function (item, key) {
    var keys = key;
    keys = (keys || 'Name').split(',');
    var index = -1;
    for (var i = 0; i < this.length; i++) {
        if (typeof item === 'object') {
            var match = true;
            for (var j = 0; j < keys.length; j++) {
                match = match && this[i][keys[j]] === item[keys[j]];
            }

            if (match) {
                index = i;
                break;
            }
        } else {
            if (this[i] === item) {
                index = i;
                break;
            }
        }
    }

    return this.splice(index, 1);
};

// array to map
Array.prototype.toMap = function (key, value) {
    if (this.length > 0) {
        var map = new Map();
        key = key || 'key';
        value = value || 'value';
        if (!this[0][key] && this[0][key] !== 0) {
            throw new Error('the key is not exist!');
        }

        for (var i = 0; i < this.length; i++) {
            map.set(this[i][key], this[i][value]);
        }

        return map;
    }
};

// map to array
Map.prototype.toArray = function () {
    if (this.size > 0) {
        var arr = [];
        this.forEach(function (value, key) {
            arr.push({ key: key, value: value });
        });

        return arr;
    }
};

// map to object
Map.prototype.toObject = function () {
    if (this.size > 0) {
        var obj = {};
        this.forEach(function (value, key) {
            obj[key] = value;
        });

        return obj;
    }
};


/*
* jQuery 扩展方法, 返回 el 在当前 jQuery 对象中的序号
* @param { el } 任意 jQuery 对象或选择器
* @returns 返回 el 在当前 jQuery 对象中的序号
*/
jQuery.fn.getIndex = function (el) {
    var $el = $(el);

    if (this.hasValue()) {
        var index = 0;
        for (var i = 0; i < this.length; i++) {
            if (this.eq(i).equal($el)) {
                index = i;
                break;
            }
        }

        return index;
    }

    return -1;
};

/*
* jQuery 扩展方法, 判断一个元素的 attr 属性是否为 true
* @param { attr } 当前元素上的属性名称
* @returns bool 返回判断结果
*/
jQuery.fn.isTrue = function (attr) {
    var result = false;
    var value = $.com.hasValue(attr) ? (this.attr(attr) || this.attr('data-' + attr)) : (this.val() || this.attr("data-value"));

    if ($.com.hasValue(value)) {
        value = value.toUpperCase();
        result = value === "TRUE";
    }

    return result;
};

/*
* jQuery 扩展方法, 为一个组件增加/去掉必填验证
* @param { arg } bool 值是否必填
* @returns 返回元素的jQuery对象本身
*/
jQuery.fn.required = function (arg) {
    return this.each(function () {
        var $this = $(this);
        if (arg !== false) {
            $this.attr("required", "required");
            if ($this.closest('.form-group')) {
                $this.closest(".form-group").find(".required").show();
            }
        } else {
            $this.removeAttr("required", "required");
            if ($this.closest('.form-group')) {
                $this.closest(".form-group").find(".required").hide();
            }
        }
    });
};

/**
 * TODO Unknown usage
 * @param {any} arg
 */
jQuery.fn.inputSelect = function (arg) {
    var $this = $(this);
    //初始化组件
    if ($.com.hasValue(arg)) {
        var $template = $('#__InputDropDownList').children().clone();
        var $select = $template.find("select.inputSelect");
        var dataSource = arg.dataSource;
        if ($.com.hasValue(dataSource)) {
            if ($.com.isArray(dataSource.data)) {
                $.each(dataSource.data, function (i, x) {
                    var option = document.createElement("option");
                    dataSource.textField = dataSource.textField || "Name";
                    dataSource.valueField = dataSource.valueField || "Id";

                    $(option).html(x[dataSource.textField]);
                    $(option).attr("value", x[dataSource.valueField]);

                    if ($.com.hasValue(dataSource.selectValue) && dataSource.selectValue == x[dataSource.valueField]) {
                        $(option).attr("selected", "selected");
                    }

                    $select.append(option);
                });
            }
        }

        $this.replaceWith($template);
        $template.prepend($this);
    } else {
        //返回组件对象值

    }
}

/*
* jQuery 扩展方法, 判断一个元素是否为有值的 jQuery 对象
* @returns bool 返回判断结果
*/
jQuery.fn.hasValue = function () {
    return this.hasOwnProperty('length') && this.length > 0;
};

/*
* jQuery 扩展方法, 判断两个 jQuery 对象是否相等
* @param { el } 任意 jQuery 对象或选择器
* @returns bool 返回判断结果
*/
jQuery.fn.equal = function (el) {
    var $el = $(el);
    var result = false;
    if (this.hasValue() && $el.hasValue() && this.length === $el.length) {
        result = true;
        for (var i = 0; i < this.length; i++) {
            if (this[i] !== $el[i]) {
                result = false;
                break;
            }
        }
    }

    return result;
};

/*
* jQuery 扩展方法, 判断一个元素是否 form 元素
* @returns bool 返回判断结果
*/
jQuery.fn.isForm = function () {
    return this.attr(_config_.attribute.plugin) === 'form' && $.com.hasValue(this.attr(_config_.attribute.field));
};

/*
* jQuery 扩展方法, 判断一个元素是否 grid 元素
* @returns bool 返回判断结果
*/
jQuery.fn.isGrid = function () {
    return this.attr(_config_.attribute.plugin) === 'grid';
};

/*
* jQuery 扩展方法, 判断一个元素是否 popup 元素
* @returns bool 返回判断结果
*/
jQuery.fn.isPopup = function () {
    return this.attr(_config_.attribute.plugin) === 'popup' && $.com.hasValue(this.attr(_config_.attribute.popup));
};

/*
* jQuery 扩展方法, 判断一个元素是否 field 元素
* @returns bool 返回判断结果
*/
jQuery.fn.isField = function () {
    return $.com.hasValue(this.attr(_config_.attribute.field)) && !this.isForm();
};

/*
* jQuery 扩展方法, 判断一个元素是否 button 元素
* @returns bool 返回判断结果
*/
jQuery.fn.isButton = function () {
    return $.com.hasValue(this.attr(_config_.attribute.button));
};

/*
* jQuery 扩展方法, 判断两个 jQuery 对象是否相等
* @param { el } 任意 jQuery 对象或选择器
* @returns bool 返回判断结果
*/
jQuery.fn.equal = function (el) {
    var $el = $(el);
    var result = false;
    if (this.hasValue() && $el.hasValue() && this.length === $el.length) {
        result = true;
        for (var i = 0; i < this.length; i++) {
            if (this[i] !== $el[i]) {
                result = false;
                break;
            }
        }
    }

    return result;
};

/*
 * jQuery 扩展方法, 判断一个元素是否为另一个元素的父级元素
 * 此处使用 DOM contains 方法判断包含
 * @param { el } 任意 jQuery 对象或选择器
 * @returns bool 返回判断结果
 */
jQuery.fn.isParentOf = function (el) {
    return this[0] !== el && this[0].contains(el);
};

/*
 * jQuery 扩展方法, 判断一个元素是否为另一个元素的子级元素
 * 此处使用 DOM contains 方法判断包含
 * @param { el } 任意 jQuery 对象或选择器
 * @returns bool 返回判断结果
 */
jQuery.fn.isChildOf = function (el) {
    return this[0] !== el && el.contains(this[0]);
};

/*
* jQuery 扩展方法, 判断一个元素是否属于另一个 form 元素
* @param { el } 任意 jQuery 对象或选择器
* @returns bool 返回判断结果
*/
jQuery.fn.isBelongToForm = function (el) {
    var $el = $(el);
    var $form = this.parents(_config_.selector.form).first();
    var $notForm = this.parents(_config_.selector.notForm).first();
    return $form.equal($el) && (!$notForm.hasValue() || $form.isChildOf($notForm[0]));
};

/*
* jQuery 扩展方法, 从jQuery 对象中移除 el
* @param { el } 任意 jQuery 对象或选择器
* @returns jQuery 返回移除后的对象
*/
jQuery.fn.removeItem = function (el) {
    var $el = $(el);

    if (this.hasValue()) {
        var index = 0;
        for (var i = 0; i < this.length; i++) {
            if (this.eq(i).equal($el)) {
                index = i;
                break;
            }
        }

        this.splice(index, 1);
    }

    return this;
};
